home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 January / EnigmA AMIGA RUN 33 (1999)(G.R. Edizioni)(IT)[!][issue 1999-01].iso / earcd / apus / boothack / old / bh980730.lha / bh980730 / ppc_boot.c < prev    next >
C/C++ Source or Header  |  1980-01-05  |  8KB  |  398 lines

  1. /****************************************************************************
  2.  * ppc_boot.c -- This program initializes the PPC on a Phase5 PowerUp board
  3.  *               and boots the kernel.
  4.  *
  5.  * Copyright 1997, 1998 by Jesper Skov (jskov@cygnus.co.uk)
  6.  ***************************************************************************/
  7.  
  8. #define SYMBOL_NAME_STR(X) #X
  9.  
  10. #define INTENA 0xdff09a
  11. #define INTREQ 0xdff09c
  12. #define DMACON 0xdff096
  13.  
  14. #define CHIP_PTR (0xfff00)
  15.  
  16. #define REG_INTREG (0xf60028)
  17. #define REGINTREG_SETRESET  (0x80)
  18. #define REGINTREG_INTMASTER (0x01)
  19.  
  20. #define REG_INTLVL (0xf60038)
  21. #define REGINTLVL_SETRESET (0x80)
  22. #define REGINTLVL_LVL7     (0x40)
  23.  
  24. #define REG_SHADOW (0xf60018)
  25. #define REGSHADOW_SETRESET (0x80)
  26. #define REGSHADOW_SHADOW   (0x01)
  27.  
  28. #include <exec/types.h>
  29. #include <exec/nodes.h>
  30. #include <exec/lists.h>
  31. #include <exec/memory.h>
  32. #include <powerup/ppclib/interface.h>
  33. #include <powerup/gcclib/powerup_protos.h>
  34. #include <powerup/ppclib/tasks.h>
  35.  
  36. void goSupervisor(void);
  37. void relocate(void);
  38. extern char relocateEnd;
  39.  
  40. void progress_init (void);
  41. void progress (char);
  42.  
  43. unsigned int main(void)
  44. {
  45.     int i;
  46.     unsigned long *s, *d;
  47.     unsigned long ptr;
  48.  
  49.     register unsigned long r0 __asm("r0");
  50.     register unsigned long r3 __asm("r3");
  51.  
  52.     progress_init ();
  53.  
  54.     /* Wait for signal from m68k. */
  55.     progress ('W');
  56.     {
  57.         void            *PPCPort;
  58.  
  59.         if (PPCPort=(void*) PPCGetTaskAttr(PPCTASKTAG_MSGPORT))
  60.         {
  61.             progress ('w'); /* Wait */
  62.             PPCWaitPort(PPCPort);
  63.             progress ('r'); /* Received */
  64.         } else {
  65.             progress ('X');
  66.             for (;;);
  67.         }
  68.     }
  69.     progress ('!');
  70.  
  71.     /* Start Shutdown. */
  72.     progress ('S');
  73.  
  74.     progress ('d');    /* Disable IRQs. */
  75.     *(unsigned short*) INTENA = 0x7fff;
  76.     progress ('d');    /* (Stall for a bit.) */
  77.     *(unsigned short*) INTREQ = 0x7fff;
  78.     progress ('d');    /* Disable DMA. */
  79.     *(unsigned short*) DMACON = 0x03ff;
  80.  
  81.     
  82.     progress ('s');    /* Get the PR bit set. */
  83.     goSupervisor();
  84.     
  85.     progress ('i');    /* Change interrupt master. */
  86.     *(unsigned char*) REG_INTREG = REGINTREG_INTMASTER;
  87.     
  88.     progress ('w');    /* Give the m68k a wedgie. */
  89.     *(unsigned char*) REG_INTLVL = REGINTLVL_LVL7;
  90.     
  91.     /* Stall a bit to allow the m68k to disable its MMU. */
  92.     {
  93.         int i;
  94.         for (i = 0; i < 50000; i++);
  95.     }
  96.     progress ('!');    /* Done! PPC owns the Amiga. */
  97.  
  98.     progress ('1');
  99.     PPCCacheFlushAll();
  100.     __asm __volatile (
  101.         /* Disable caches. */
  102.         "mfspr 4,1008       \n\t" /* HID0 */
  103.         "lis   3,0          \n\t"
  104.         "ori   3,3,0xc000   \n\t" /* HID0_ICE|HID0_DCE */
  105.         "andc  4,4,3        \n\t"
  106.         "sync               \n\t"
  107.         "isync              \n\t"
  108.         "mtspr 1008,4       \n\t" /* HID0 */
  109.         /* Invalidate caches. */
  110.         "mfspr 4,1008       \n\t" /* HID0 */
  111.         "lis   3,4          \n\t"
  112.         "ori   3,3,0x0c00   \n\t" /* HID0_ICFI|HID0_DCFI */
  113.         "or    3,3,4        \n\t"
  114.         "isync              \n\t"
  115.         "sync               \n\t"
  116.         "mtspr 1008,3       \n\t" /* HID0 */
  117.         "mtspr 1008,4       \n\t" /* HID0 */
  118.         /* Disable address translation and interrupts. */
  119.         "mfmsr 4            \n\t"
  120.         "lis   3,0          \n\t"
  121.         "ori   3,3,0x8030   \n\t" /* MSR_EE|MSR_IR|MSR_DR */
  122.         "andc  4,4,3        \n\t"
  123.         "isync              \n\t"
  124.         "mtmsr 4            \n\t"
  125.         "sync               \n\t"
  126.         ::: "r3", "r4");
  127.  
  128.     progress ('2');
  129.  
  130. #if 0 
  131.     { 
  132.         /* I don't know if this works so it is disabled until someone with a
  133.            blizzard verifies the effect. mm/init.c will need to be adjusted
  134.            if this code is activated (init makes presumptions about
  135.            shadowing based on memory size). */ 
  136.         unsigned char* reg_shadow =    (unsigned char*) REG_SHADOW; 
  137.         *reg_shadow = (REGSHADOW_SETRESET |    REGSHADOW_SHADOW);
  138.     } 
  139. #endif 
  140.  
  141.     progress ('3');
  142.  
  143.     {
  144.         const unsigned long *info;
  145.         /* Get info-ptr from CHIP_PTR. */
  146.         info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  147.  
  148.         /* Relocate code to memory just above info. */
  149.         ptr = (unsigned long)info + 0x0200;
  150.         ptr = ptr + 4 - (ptr % 4);
  151.  
  152.         s = (unsigned long*) &relocate;
  153.         d = (unsigned long*) ptr;
  154.         for(i = (((unsigned long)&relocateEnd) - ((unsigned long)s))/4;
  155.             i >= 0; i--){
  156.                 *d = *s;
  157.                 d++;
  158.                 s++;
  159.             }
  160.  
  161.         progress ('4');
  162.     
  163.         /* Jump to relocated code. */
  164.         __asm __volatile (
  165.                  /* Change stack. */
  166.                  "mr   1,%0 \n\t"
  167.                  "mtlr %1   \n\t"
  168.                  "blr       \n\t"
  169.                  : /* no outputs */
  170.                  : "r" (info[8]), "r" (ptr)
  171.                  /* no return */);
  172.     
  173.     }
  174.  
  175.     /* fake a noreturn */
  176.     for (;;);
  177. }
  178.  
  179. void relocate(void)
  180. {
  181.     const unsigned long *info;
  182.     unsigned char *s, *d, *e;
  183.     
  184.     progress ('5');
  185.  
  186.     /* Get info-ptr from CHIP_PTR. */
  187.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  188.  
  189.     /* Verify checksum. */
  190.     if (info[7])
  191.     {
  192.         int i = (info[2] + info[3]) / 4;
  193.         unsigned char* k_p = (unsigned char*) info[0];
  194.         unsigned long kcs = 0;
  195.         
  196.         while (i--)
  197.         {
  198.             unsigned long w = 0;
  199.                 
  200.             w |= *k_p++;
  201.             w <<= 8;
  202.             w |= *k_p++;
  203.             w <<= 8;
  204.             w |= *k_p++;
  205.             w <<= 8;
  206.             w |= *k_p++;
  207.  
  208.                 
  209.             kcs = kcs ^ i;
  210.             kcs = kcs ^ w;
  211.         }
  212.         progress ('C');
  213.         progress ('1');
  214.         if (info[7] == kcs)
  215.             progress ('+');
  216.         else
  217.             progress ('-');
  218.     }
  219.  
  220.     /* Copy kernel to memstart */
  221.     s = (unsigned char *) info[0];
  222.     d = (unsigned char *) info[1];
  223.     e = (unsigned char *) (info[1] + info[2] + info[3]);
  224.     while(d != e){
  225.         *d = *s;
  226.         s++;
  227.         d++;
  228.     }
  229.  
  230.     progress ('6');
  231.  
  232.     /* Verify checksum. */
  233.     if (info[7])
  234.     {
  235.         int i = (info[2] + info[3]) / 4;
  236.         unsigned char* k_p = (unsigned char*) info[1];
  237.         unsigned long kcs = 0;
  238.         
  239.         while (i--)
  240.         {
  241.             unsigned long w = 0;
  242.                 
  243.             w |= *k_p++;
  244.             w <<= 8;
  245.             w |= *k_p++;
  246.             w <<= 8;
  247.             w |= *k_p++;
  248.             w <<= 8;
  249.             w |= *k_p++;
  250.  
  251.                 
  252.             kcs = kcs ^ i;
  253.             kcs = kcs ^ w;
  254.         }
  255.         progress ('C');
  256.         progress ('2');
  257.         if (info[7] == kcs)
  258.             progress ('+');
  259.         else
  260.             progress ('-');
  261.     }
  262.     
  263.     /* Copy ramdisk to memory end. */
  264.     d = (unsigned char *) info[1] + info[5];
  265.     e = d - info[4];
  266.     s = s + info[4];
  267.     while(d != e){
  268.         s--;
  269.         d--;
  270.         *d = *s;
  271.     }
  272.  
  273.     progress ('7');
  274.  
  275.     /* Let 0xfff00000 contain sum used for VTOP/PTOV in head.S. */
  276.     /* Also put it at kernel start since kernel copies the vectors
  277.      * to their proper location after modifying a few instructions.
  278.      */
  279. #define KERNELBASE 0xC0000000
  280.     *((unsigned long *)0xfff00000) = info[1] - KERNELBASE;
  281.     *((unsigned long *) info[1]) = info[1] - KERNELBASE;
  282.  
  283.     progress ('K');
  284.     {
  285.         register unsigned long r3 __asm("r3");
  286.         register unsigned long r4 __asm("r4");
  287.         register unsigned long r5 __asm("r5");
  288.         register unsigned long r6 __asm("r6");
  289.         register unsigned long r7 __asm("r7");
  290.  
  291.         /* initrd pointers (virtual addresses) */
  292.         if (info[4]){
  293.             /* end of rd */
  294.             r5 = info[5] + KERNELBASE;
  295.             /* start of rd */
  296.             r4 = r5 - info[4];
  297.         } else
  298.             r4 = 0;
  299.         
  300.         /* Make it easy to identify APUS in identify_machine. */
  301.         r3 = 0x61707573;
  302.         
  303.         /* Jump to kernel start. */
  304.         r7 = info[1] + 0xc;
  305.         __asm __volatile (
  306.             "mtlr 7 \n\t"
  307.             "blr    \n\t"
  308.             : /* no outputs */
  309.             : "r" (r3), "r" (r4), "r" (r5), "r" (r6), "r" (r7)
  310.             /* no return */);
  311.     }
  312.     
  313.     /* fake a noreturn */
  314.     for (;;);
  315. }
  316.  
  317. /* Play that jive... */
  318. extern char setPR, setPRend;
  319. void goSupervisor(void)
  320. {
  321.     unsigned long *s, *d;
  322.     int len = ((int) &setPRend - (int) &setPR) / 4;
  323.  
  324.     /* Copy code to TRAP entry */
  325.     d = (unsigned long*) 0xfff00700;
  326.     s = (unsigned long*) &setPR;
  327.     for(;len > 0;len--){
  328.         *d = *s;
  329.         d++;
  330.         s++;
  331.     }
  332.  
  333.     PPCCacheFlushAll();
  334.     
  335.     /* Execute code */
  336.     __asm__ (
  337.         "trap \n\t"
  338.         );
  339. }
  340.  
  341. void progress_init (void)
  342. {
  343.     const unsigned long *info;
  344.     unsigned long *mesg_base;
  345.     unsigned long* p;
  346.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  347.     mesg_base = (unsigned long*) info[6];
  348.     p = mesg_base;
  349.     
  350.     *p++ = 'SAVE';
  351.     *p++ = 'BOOT';
  352.     *p++ = (unsigned long) mesg_base;
  353.     *p++ = 0;
  354. }
  355.     
  356.  
  357. void progress (char c)
  358. {
  359.     const unsigned long *info;
  360.     char progress_state;
  361.     char* progress_ptr;
  362.     unsigned long* mesg_base;
  363.     info = (const unsigned long*) *((unsigned long*) CHIP_PTR);
  364.  
  365.     mesg_base = (unsigned long*) info[6];
  366.  
  367.     progress_ptr = mesg_base[3] + (char*)&mesg_base[4];
  368.     *progress_ptr = c;
  369.     mesg_base[3]++;
  370. }
  371.  
  372. asm(
  373.     ".text\n"
  374.     ".align 4\n"
  375.     SYMBOL_NAME_STR(setPR) ":
  376. /* Increase the return EA so we get to the next instruction */
  377. mtsprg       1,1
  378. mfsrr0       1
  379. addi         1,1,4
  380. mtsrr0       1
  381. mfsprg       1,1
  382. /* Fiddle the PR bit */
  383. mfsrr1       0
  384. rlwinm       0,0,0,18,16
  385. mtsrr1       0
  386. rfi
  387. "
  388.     SYMBOL_NAME_STR(setPRend) ":
  389. ");
  390.  
  391. asm(
  392.     ".text\n"
  393.     ".align 4\n"
  394.     SYMBOL_NAME_STR(relocateEnd) ":
  395. nop
  396. "
  397.     );
  398.